from rest_framework.exceptions import APIException
from rest_framework.fields import empty

from rest_framework import serializers, status
from rest_framework.request import Request


class ValidationError(APIException):
    status_code = status.HTTP_400_BAD_REQUEST
    default_detail = 'Invalid input.'
    default_code = 'invalid'

    def __init__(self, detail=None):
        self.detail = detail


class BaseSerializer(serializers.ModelSerializer):
    user_type = "user"
    user_fields = ['create_by', 'modified_by']

    def __init__(self, instance=None, data=empty, request=None, **kwargs):
        super().__init__(instance, data, **kwargs)
        self.request: Request = request or self.context.get("request", None)
        self.user = self.request.user if self.request else "AnonymousUser"

    def create(self, validated_data):
        if str(self.user) != "AnonymousUser":
            validated_data['create_by'] = self.user
            validated_data['modified_by'] = self.user
        return super().create(validated_data)

    def update(self, instance, validated_data):
        if str(self.user) != "AnonymousUser":
            validated_data['modified_by'] = self.user
        return super().update(instance, validated_data)

    def custom_validation_error(self, message):
        raise ValidationError(message)


class SerializerFactory:

    @staticmethod
    def build(model, fields, **kwargs):
        meta = type(str('Meta'), (object,), {'model': model, 'fields': fields})
        kwargs.update({'Meta': meta})
        serializer_clss = type(str('%sModelSerializerByType' % model._meta.object_name), (BaseSerializer,), kwargs)
        return serializer_clss
